package stock;

import requetes.Deplacement;
import java.util.Vector;
import java.util.Iterator;

import java.util.Random;


/**
 * 
 * Classe qui g&egrave;re le stock des {@link Deplacement} 
 * et qui est utilis&eacute; dans {@link controle.Controle}.
 * <p>
 * Cette classe trie les requetes qu'on lui transmets par
 * sens de d&eacute;placement et par priorit&eacute;.
 *
 * @author Grivolet Mylene
 * @author Bourgeois Jean-Louis
 * @author Ciabaud Yoann
 *
 * @see 	Deplacement
 * @see 	controle.Controle
 */
public class Stock {

	
	/** Liste de {@link Deplacement} montants */
	private Vector<Deplacement> listeMontees;
	/** Liste de {@link Deplacement} descendants */
	private Vector<Deplacement> listeDescentes;

	/** Initialise un stock vide */
	public Stock()
	{
		//On initialise les listes
		listeMontees = new Vector<Deplacement>();
		listeDescentes = new Vector<Deplacement>();
	}

	
	/**
	 * Ajoute un deplacement au stock 
	 * 
	 * @param d		Requete a ajouter 
	*/
	public void ajouterRequete( Deplacement d )
	{

		//Si le deplacement est nul on ne fait rien
		if( d == null )
		{
			System.err.println("[Requete] ajouterRequete: Requete vide!");
			return;
		}
		//sinon si c'est un deplacement montant
		//on l'insere dans liste des montees
		else if( d.sens == Deplacement.MONTEE )
			ajouterMontee(d);
		//sinon si c'est un deplacement descendant
		//on l'insere dans liste des descentes
		else if( d.sens == Deplacement.DESCENTE )
			ajouterDescente(d);
		
	}
	
	
	/** Vide le stock */
	public void viderStock()
	{
		//On efface les deux listes
		listeMontees.clear();
		listeDescentes.clear();
	}
	

	/**
	 * Retourne le premier deplacement &agrave; traiter
	 *
	 * @param sens	sens du prochain deplacement a recuperer
	 * @return 	prochain deplacement a traiter ( null en cas d'erreur ou si la liste se vide )
	 *
	 * @see 	Deplacement
	 */
	public Deplacement prochain(int sens){
		
		//le deplacement retourne
		Deplacement d;
		
		//selon le sens
		switch(sens)
		{
			//sens montant
			case Deplacement.MONTEE:
				//si la listeest vide on retourne null
				if(listeMontees.isEmpty() )
					return null;
				
				//on recupere le premier element
				d = listeMontees.firstElement();
				//on le supprime de la liste
				listeMontees.remove(0);
				break;
				
			//sens descendant
			case Deplacement.DESCENTE:
				//si la listeest vide on retourne null
				if( listeDescentes.isEmpty() )
					return null;
				
				//on recupere le premier element
				d = listeDescentes.firstElement();
				//on le supprime de la liste
				listeDescentes.remove(0);
				break;
			
			//erreur
			default:
				d = null;
		}
		
		//retourne le deplacement
		return d;
	}

	
	
	
	/** 
	 * Ajoute un element dans la liste des Descentes
	 * En prenant soin de laisser la liste triee
	 *
	 * @param d	Deplacement a inserer
	 */		
	private void ajouterDescente( Deplacement d )
	{
		//deplacement pointee
		Iterator<Deplacement> I = listeDescentes.iterator();
		//deplacement pointe
		Deplacement tmp;
		//position courante
		int position = 0;
		
		//si la liste est vide
		if( !I.hasNext() )
		{
			listeDescentes.add(0, d);
			return;
		}
		
		
		//On recherche la position du premier etage superieur
		while( I.hasNext() )
		{
			tmp = I.next();
			
			//Si on est inferieur on insere
			if( d.etage > tmp.etage )
				break;
			//Si on est egal c'est terminer
			if( d.etage == tmp.etage )
			{
				listeDescentes.get(position).boutons |= d.boutons;
				return;
			}
			
			position++;
		}
		
		
		listeDescentes.add(position, d);
	}
	
	/** 
	 * Ajoute un element dans la liste des montees
	 * En prenant soin de laisser la liste triee
	 *
	 * @param d	Deplacement a inserer
	 */
	private void ajouterMontee( Deplacement d )
	{
		//iterateur
		Iterator<Deplacement> I = listeMontees.iterator();
		//deplacement pointee
		Deplacement tmp;
		//position courante
		int position = 0;
		
		//si la liste est vide
		if( !I.hasNext() )
		{
			listeMontees.add(0, d);
			return;
		}
		
		
		//On recherche la position du premier etage superieur
		while( I.hasNext() )
		{
			tmp = I.next();
			
			//Si on est inferieur on insere
			if( d.etage < tmp.etage )
				break;
			//Si on est egal c'est terminer
			if( d.etage == tmp.etage )
			{
				listeMontees.get(position).boutons |= d.boutons ;
				return;
			}
			position++;
		}

		
		listeMontees.add(position, d);
	}

}
